home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <netdb.h>
- #include <sys/types.h>
- #include <sys/syslog.h>
- #include <sys/socket.h>
- #include <sys/errno.h>
- #include <netinet/in.h>
- #include <arpa/nameser.h>
-
- #include <exec/nodes.h>
- #include <exec/lists.h>
-
- // Protos
- #include <proto/exec.h>
- #include <proto/miami.h>
- #include <proto/socket.h>
- int dn_expand(char *msg, char *eomorig, char *comp_dn, char *exp_dn, int length);
- u_char dn_comp(char *exp_dn, char *comp_dn, int length, char **dnptrs, char **lastdnptr);
-
- #include "rev.h"
- char version[] = "\0$VER: " PROGNAME PROGVERSION " " __AMIGADATE__;
-
- struct hostinfo {
- struct MinNode Node;
- char name[MAXDNAME];
- LONG netnumber;
- };
- struct MinList hostlist;
- char Line[1024];
- char hostname[MAXHOSTNAMELEN];
- char *curnet="";
-
-
- void send_err(int s,char *msg,int msglen,struct sockaddr_in *to,LONG tolen,short rcode)
- {
- HEADER *h;
-
- h=(HEADER *)msg+sizeof(HEADER);
- h->qr=1;
- h->rcode=rcode;
- sendto(s,msg,msglen,0,(struct sockaddr *)to,tolen);
-
- #ifdef DEBUG
- switch(rcode)
- {
- case FORMERR: puts("FORMERR send");break;
- case SERVFAIL: puts("FORMFAIL send");break;
- case NXDOMAIN: puts("NXDOMAIN send");break;
- default: puts("UNKNOWN ERROR send");break;
- }
- #endif
- }
-
- main()
- {
- struct servent *sp;
- struct sockaddr_in sin;
- struct sockaddr_in from;
- struct hostinfo *hp,*hi;
- struct hostent *host;
- LONG fromlen;
- char msg[PACKETSZ];
- char *lmsg;
- char dnbuf[MAXDNAME];
- char *cp,*eom;
- int msglen;
- int s,n;
- short type,class;
-
- sp=getservbyname("domain","udp");
- if(!sp)
- {
- fprintf(stderr,"nameserver: tcp/nameserver: unknown service\n");
- exit(1);
- }
-
- s=socket(AF_INET,SOCK_DGRAM,0);
- if(s==-1)
- {
- perror("nameserver: create socket");
- exit(1);
- }
-
- bzero(&sin,sizeof(sin));
- sin.sin_port=sp->s_port;
-
- if(bind(s,(struct sockaddr *)&sin,sizeof(sin))==-1)
- {
- perror("nameserver: bind");
- exit(1);
- }
-
- if(gethostname(hostname,sizeof(hostname))==-1)
- {
- perror("nameserver: gethostname");
- exit(1);
- }
- if(cp=strchr(hostname,'.')) curnet=cp;
-
- NewList((struct List *)&hostlist);
-
- #ifdef DEBUG
- printf("nameserver started\n");
- #endif
- for(;;)
- {
- fromlen=sizeof(from);
- if((msglen=recvfrom(s,msg,sizeof(msg),0,(struct sockaddr *)&from,&fromlen))==-1)
- {
- perror("nameserver: recvfrom");
- }
- else
- {
- HEADER *h;
- h=(HEADER *)msg;
- cp=msg+sizeof(HEADER);
- eom=msg+msglen;
- #ifdef DEBUG
- printf( "datagram received:\n"
- " from : %s\n"
- " opcode : %d\n"
- " qdqount: %d\n"
- ,inet_ntoa(from.sin_addr)
- ,h->opcode
- ,h->qdcount
- );
- #endif
- switch(h->opcode)
- {
- case QUERY:
- if(h->qdcount!=1 || h->ancount || h->nscount || h->arcount)
- {
- h->qdcount=0;
- h->ancount=0;
- h->nscount=0;
- h->arcount=0;
- send_err(s,msg,msglen,&from,fromlen,FORMERR);
- continue;
- }
- if((n=dn_expand(msg,eom,cp,dnbuf,sizeof(dnbuf)))<0)
- {
- send_err(s,msg,msglen,&from,fromlen,FORMERR);
- continue;
- }
- cp+=n;
- GETSHORT(type, cp);
- GETSHORT(class, cp);
- if(cp>eom)
- {
- send_err(s,msg,msglen,&from,fromlen,FORMERR);
- continue;
- }
- #ifdef DEBUG
- printf(" host : %s\n",dnbuf);
- printf(" type : %d\n",type);
- printf(" class : %d\n",class);
- #endif
- if(type!=T_A || class!=C_IN)
- {
- send_err(s,msg,msglen,&from,fromlen,NOTIMP);
- continue;
- }
-
- // search host in cache list
- hp=NULL;
- for(hi=(struct hostinfo *)hostlist.mlh_Head;hi!=(struct hostinfo *)&hostlist.mlh_Tail;hi=(struct hostinfo *)hi->Node.mln_Succ)
- {
- if(!strcmp(hi->name,dnbuf))
- {
- hp=hi;
- break;
- }
- }
-
- if(!hp) // not found
- {
- if( !(host = gethostbyname( dnbuf ) ) )
- {
- send_err(s,msg,msglen,&from,fromlen,NXDOMAIN);
- continue;
- }
- else
- {
- struct hostinfo *newhi;
-
- if(newhi=malloc(sizeof(struct hostinfo)))
- {
- strcpy(newhi->name,dnbuf);
- memcpy( &newhi->netnumber, &host->h_addr_list[ 0 ][ 0 ], 4 );
- #ifdef DEBUG
- printf("add '%s' to cache\n",newhi->name);
- #endif
- AddTail((struct List *)&hostlist,(struct Node *)newhi);
- hi = newhi;
- }
- }
- }
-
- lmsg=msg+sizeof(msg);
- if((n=dn_comp(dnbuf,cp,lmsg-cp,NULL,NULL))<0)
- {
- send_err(s,msg,msglen,&from,fromlen,SERVFAIL);
- continue;
- }
- cp+=n;
- if(cp+14>lmsg)
- {
- send_err(s,msg,msglen,&from,fromlen,SERVFAIL);
- continue;
- }
-
- PUTSHORT(type, cp);
- PUTSHORT(class, cp);
- PUTLONG(100000,cp);
- PUTSHORT(sizeof(LONG),cp);
- PUTLONG(hi->netnumber,cp);
-
- h->qr=1;
- h->rcode=NOERROR;
- h->ancount=1;
- sendto(s,msg,cp-msg,0,(struct sockaddr *)&from,fromlen);
- #ifdef DEBUG
- printf("answer: %s(%s) send\n",dnbuf,Inet_NtoA(hi->netnumber));
- #endif
- break;
- default:
- send_err(s,msg,msglen,&from,fromlen,NOTIMP);
- }
- }
- }
- }
-